#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

#define NUM_THREADS 5
#define FILE_PATH "output.txt"

pthread_mutex_t file_mutex;

void* write_to_file(void* threadid) {
    long tid = (long) threadid;
    char buffer[100];
    snprintf(buffer, sizeof(buffer), "Thread %ld writing to the file.\n", tid);

    // Open file for appending
    int fd = open(FILE_PATH, O_WRONLY | O_CREAT | O_APPEND, 0644);
    if (fd == -1) {
        perror("Error opening file");
        pthread_exit(NULL);
    }

    // Lock the file before writing to ensure safe access
    pthread_mutex_lock(&file_mutex);

    // Write to the file
    ssize_t bytes_written = write(fd, buffer, strlen(buffer));
    if (bytes_written == -1) {
        perror("Error writing to file");
    } else {
        printf("Thread %ld wrote %ld bytes\n", tid, bytes_written);
    }

    // Unlock the file
    pthread_mutex_unlock(&file_mutex);

    // Close the file
    close(fd);
    pthread_exit(NULL);
}

int main() {
    pthread_t threads[NUM_THREADS];
    int rc;
    long t;

    // Initialize the mutex
    pthread_mutex_init(&file_mutex, NULL);

    // Remove old file if it exists
    unlink(FILE_PATH);

    // Create threads
    for (t = 0; t < NUM_THREADS; t++) {
        printf("Creating thread %ld\n", t);
        rc = pthread_create(&threads[t], NULL, write_to_file, (void*)t);
        if (rc) {
            printf("Error: unable to create thread, %d\n", rc);
            exit(-1);
        }
    }

    // Join threads
    for (t = 0; t < NUM_THREADS; t++) {
        pthread_join(threads[t], NULL);
    }

    // Destroy the mutex
    pthread_mutex_destroy(&file_mutex);

    printf("All threads have finished writing.\n");
    return 0;
}

